home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-08-13 | 35.2 KB | 1,055 lines |
- @c Copyright (C) 1996, 1997 John W. Eaton
- @c This is part of the Octave manual.
- @c For copying conditions, see the file gpl.tex.
-
- @node Functions and Scripts, Error Handling, Statements, Top
- @chapter Functions and Script Files
- @cindex defining functions
- @cindex user-defined functions
- @cindex functions, user-defined
- @cindex script files
-
- Complicated Octave programs can often be simplified by defining
- functions. Functions can be defined directly on the command line during
- interactive Octave sessions, or in external files, and can be called just
- like built-in functions.
-
- @menu
- * Defining Functions::
- * Multiple Return Values::
- * Variable-length Argument Lists::
- * Variable-length Return Lists::
- * Returning From a Function::
- * Function Files::
- * Script Files::
- * Dynamically Linked Functions::
- * Organization of Functions::
- @end menu
-
- @node Defining Functions, Multiple Return Values, Functions and Scripts, Functions and Scripts
- @section Defining Functions
- @cindex @code{function} statement
- @cindex @code{endfunction} statement
-
- In its simplest form, the definition of a function named @var{name}
- looks like this:
-
- @example
- @group
- function @var{name}
- @var{body}
- endfunction
- @end group
- @end example
-
- @noindent
- A valid function name is like a valid variable name: a sequence of
- letters, digits and underscores, not starting with a digit. Functions
- share the same pool of names as variables.
-
- The function @var{body} consists of Octave statements. It is the
- most important part of the definition, because it says what the function
- should actually @emph{do}.
-
- For example, here is a function that, when executed, will ring the bell
- on your terminal (assuming that it is possible to do so):
-
- @example
- @group
- function wakeup
- printf ("\a");
- endfunction
- @end group
- @end example
-
- The @code{printf} statement (@pxref{Input and Output}) simply tells
- Octave to print the string @code{"\a"}. The special character @samp{\a}
- stands for the alert character (ASCII 7). @xref{Strings}.
-
- Once this function is defined, you can ask Octave to evaluate it by
- typing the name of the function.
-
- Normally, you will want to pass some information to the functions you
- define. The syntax for passing parameters to a function in Octave is
-
- @example
- @group
- function @var{name} (@var{arg-list})
- @var{body}
- endfunction
- @end group
- @end example
-
- @noindent
- where @var{arg-list} is a comma-separated list of the function's
- arguments. When the function is called, the argument names are used to
- hold the argument values given in the call. The list of arguments may
- be empty, in which case this form is equivalent to the one shown above.
-
- To print a message along with ringing the bell, you might modify the
- @code{beep} to look like this:
-
- @example
- @group
- function wakeup (message)
- printf ("\a%s\n", message);
- endfunction
- @end group
- @end example
-
- Calling this function using a statement like this
-
- @example
- wakeup ("Rise and shine!");
- @end example
-
- @noindent
- will cause Octave to ring your terminal's bell and print the message
- @samp{Rise and shine!}, followed by a newline character (the @samp{\n}
- in the first argument to the @code{printf} statement).
-
- In most cases, you will also want to get some information back from the
- functions you define. Here is the syntax for writing a function that
- returns a single value:
-
- @example
- @group
- function @var{ret-var} = @var{name} (@var{arg-list})
- @var{body}
- endfunction
- @end group
- @end example
-
- @noindent
- The symbol @var{ret-var} is the name of the variable that will hold the
- value to be returned by the function. This variable must be defined
- before the end of the function body in order for the function to return
- a value.
-
- Variables used in the body of a function are local to the
- function. Variables named in @var{arg-list} and @var{ret-var} are also
- local to the function. @xref{Global Variables}, for information about
- how to access global variables inside a function.
-
- For example, here is a function that computes the average of the
- elements of a vector:
-
- @example
- @group
- function retval = avg (v)
- retval = sum (v) / length (v);
- endfunction
- @end group
- @end example
-
- If we had written @code{avg} like this instead,
-
- @example
- @group
- function retval = avg (v)
- if (is_vector (v))
- retval = sum (v) / length (v);
- endif
- endfunction
- @end group
- @end example
-
- @noindent
- and then called the function with a matrix instead of a vector as the
- argument, Octave would have printed an error message like this:
-
- @example
- @group
- error: `retval' undefined near line 1 column 10
- error: evaluating index expression near line 7, column 1
- @end group
- @end example
-
- @noindent
- because the body of the @code{if} statement was never executed, and
- @code{retval} was never defined. To prevent obscure errors like this,
- it is a good idea to always make sure that the return variables will
- always have values, and to produce meaningful error messages when
- problems are encountered. For example, @code{avg} could have been
- written like this:
-
- @example
- @group
- function retval = avg (v)
- retval = 0;
- if (is_vector (v))
- retval = sum (v) / length (v);
- else
- error ("avg: expecting vector argument");
- endif
- endfunction
- @end group
- @end example
-
- There is still one additional problem with this function. What if it is
- called without an argument? Without additional error checking, Octave
- will probably print an error message that won't really help you track
- down the source of the error. To allow you to catch errors like this,
- Octave provides each function with an automatic variable called
- @code{nargin}. Each time a function is called, @code{nargin} is
- automatically initialized to the number of arguments that have actually
- been passed to the function. For example, we might rewrite the
- @code{avg} function like this:
-
- @example
- @group
- function retval = avg (v)
- retval = 0;
- if (nargin != 1)
- usage ("avg (vector)");
- endif
- if (is_vector (v))
- retval = sum (v) / length (v);
- else
- error ("avg: expecting vector argument");
- endif
- endfunction
- @end group
- @end example
-
- Although Octave does not automatically report an error if you call a
- function with more arguments than expected, doing so probably indicates
- that something is wrong. Octave also does not automatically report an
- error if a function is called with too few arguments, but any attempt to
- use a variable that has not been given a value will result in an error.
- To avoid such problems and to provide useful messages, we check for both
- possibilities and issue our own error message.
-
- @defvr {Automatic Variable} nargin
- When a function is called, this local variable is automatically
- initialized to the number of arguments passed to the function. At the
- top level, @code{nargin} holds the number of command line arguments that
- were passed to Octave.
- @end defvr
-
- @defvr {Built-in Variable} silent_functions
- If the value of @code{silent_functions} is nonzero, internal output
- from a function is suppressed. Otherwise, the results of expressions
- within a function body that are not terminated with a semicolon will
- have their values printed. The default value is 0.
-
- For example, if the function
-
- @example
- function f ()
- 2 + 2
- endfunction
- @end example
-
- @noindent
- is executed, Octave will either print @samp{ans = 4} or nothing
- depending on the value of @code{silent_functions}.
- @end defvr
-
- @defvr {Built-in Variable} warn_missing_semicolon
- If the value of this variable is nonzero, Octave will warn when
- statements in function definitions don't end in semicolons. The default
- value is 0.
- @end defvr
-
- @node Multiple Return Values, Variable-length Argument Lists, Defining Functions, Functions and Scripts
- @section Multiple Return Values
-
- Unlike many other computer languages, Octave allows you to define
- functions that return more than one value. The syntax for defining
- functions that return multiple values is
-
- @example
- function [@var{ret-list}] = @var{name} (@var{arg-list})
- @var{body}
- endfunction
- @end example
-
- @noindent
- where @var{name}, @var{arg-list}, and @var{body} have the same meaning
- as before, and @var{ret-list} is a comma-separated list of variable
- names that will hold the values returned from the function. The list of
- return values must have at least one element. If @var{ret-list} has
- only one element, this form of the @code{function} statement is
- equivalent to the form described in the previous section.
-
- Here is an example of a function that returns two values, the maximum
- element of a vector and the index of its first occurrence in the vector.
-
- @example
- @group
- function [max, idx] = vmax (v)
- idx = 1;
- max = v (idx);
- for i = 2:length (v)
- if (v (i) > max)
- max = v (i);
- idx = i;
- endif
- endfor
- endfunction
- @end group
- @end example
-
- In this particular case, the two values could have been returned as
- elements of a single array, but that is not always possible or
- convenient. The values to be returned may not have compatible
- dimensions, and it is often desirable to give the individual return
- values distinct names.
-
- In addition to setting @code{nargin} each time a function is called,
- Octave also automatically initializes @code{nargout} to the number of
- values that are expected to be returned. This allows you to write
- functions that behave differently depending on the number of values that
- the user of the function has requested. The implicit assignment to the
- built-in variable @code{ans} does not figure in the count of output
- arguments, so the value of @code{nargout} may be zero.
-
- The @code{svd} and @code{lu} functions are examples of built-in
- functions that behave differently depending on the value of
- @code{nargout}.
-
- It is possible to write functions that only set some return values. For
- example, calling the function
-
- @example
- function [x, y, z] = f ()
- x = 1;
- z = 2;
- endfunction
- @end example
-
- @noindent
- as
-
- @example
- [a, b, c] = f ()
- @end example
-
- @noindent
- produces:
-
- @example
- a = 1
-
- b = [](0x0)
-
- c = 2
- @end example
-
- @noindent
- provided that the built-in variable @code{define_all_return_values} is
- nonzero and the value of @code{default_return_value} is @samp{[]}.
- @xref{Summary of Built-in Variables}.
-
- @defvr {Automatic Variable} nargout
- When a function is called, this local variable is automatically
- initialized to the number of arguments expected to be returned. For
- example,
-
- @example
- f ()
- @end example
-
- @noindent
- will result in @code{nargout} being set to 0 inside the function
- @code{f} and
-
- @example
- [s, t] = f ()
- @end example
-
- @noindent
- will result in @code{nargout} being set to 2 inside the function
- @code{f}.
-
- At the top level, @code{nargout} is undefined.
- @end defvr
-
- @defvr {Built-in Variable} default_return_value
- The value given to otherwise uninitialized return values if
- @code{define_all_return_values} is nonzero. The default value is
- @code{[]}.
- @end defvr
-
- @defvr {Built-in Variable} define_all_return_values
- If the value of @code{define_all_return_values} is nonzero, Octave
- will substitute the value specified by @code{default_return_value} for
- any return values that remain undefined when a function returns. The
- default value is 0.
- @end defvr
-
- @deftypefn {Function File} {} nargchk (@var{nargin_min}, @var{nargin_max}, @var{n})
- If @var{n} is in the range @var{nargin_min} through @var{nargin_max}
- inclusive, return the empty matrix. Otherwise, return a message
- indicating whether @var{n} is too large or too small.
-
- This is useful for checking to see that the number of arguments supplied
- to a function is within an acceptable range.
- @end deftypefn
-
- @node Variable-length Argument Lists, Variable-length Return Lists, Multiple Return Values, Functions and Scripts
- @section Variable-length Argument Lists
- @cindex Variable-length argument lists
- @cindex @code{...}
-
- Octave has a real mechanism for handling functions that take an
- unspecified number of arguments, so it is not necessary to place an
- upper bound on the number of optional arguments that a function can
- accept.
-
- @c XXX FIXME XXX -- should we add a note about why this feature is not
- @c compatible with Matlab 5?
-
- Here is an example of a function that uses the new syntax to print a
- header followed by an unspecified number of values:
-
- @example
- function foo (heading, ...)
- disp (heading);
- va_start ();
- ## Pre-decrement to skip `heading' arg.
- while (--nargin)
- disp (va_arg ());
- endwhile
- endfunction
- @end example
-
- The ellipsis that marks the variable argument list may only appear once
- and must be the last element in the list of arguments.
-
- @deftypefn {Built-in Function} {} va_start ()
- Position an internal pointer to the first unnamed argument and allows
- you to cycle through the arguments more than once. It is not necessary
- to call @code{va_start} if you do not plan to cycle through the
- arguments more than once. This function may only be called inside
- functions that have been declared to accept a variable number of input
- arguments.
- @end deftypefn
-
- @deftypefn {Built-in Function} {} va_arg ()
- Return the value of the next available argument and move the internal
- pointer to the next argument. It is an error to call @code{va_arg()}
- when there are no more arguments available.
- @end deftypefn
-
- Sometimes it is useful to be able to pass all unnamed arguments to
- another function. The keyword @var{all_va_args} makes this very easy to
- do. For example,
-
- @example
- @group
- function f (...)
- while (nargin--)
- disp (va_arg ())
- endwhile
- endfunction
-
- function g (...)
- f ("begin", all_va_args, "end")
- endfunction
-
- g (1, 2, 3)
-
- @print{} begin
- @print{} 1
- @print{} 2
- @print{} 3
- @print{} end
- @end group
- @end example
-
- @defvr {Keyword} all_va_args
- This keyword stands for the entire list of optional argument, so it is
- possible to use it more than once within the same function without
- having to call @code{va_start}. It can only be used within functions
- that take a variable number of arguments. It is an error to use it in
- other contexts.
- @end defvr
-
- @node Variable-length Return Lists, Returning From a Function, Variable-length Argument Lists, Functions and Scripts
- @section Variable-length Return Lists
- @cindex Variable-length return lists
- @cindex @code{...}
-
- Octave also has a real mechanism for handling functions that return an
- unspecified number of values, so it is no longer necessary to place an
- upper bound on the number of outputs that a function can produce.
-
- Here is an example of a function that uses a variable-length return list
- to produce @var{n} values:
-
- @example
- @group
- function [...] = f (n, x)
- for i = 1:n
- vr_val (i * x);
- endfor
- endfunction
-
- [dos, quatro] = f (2, 2)
- @result{} dos = 2
- @result{} quatro = 4
- @end group
- @end example
-
- As with variable argument lists, the ellipsis that marks the variable
- return list may only appear once and must be the last element in the
- list of returned values.
-
- @deftypefn {Built-in Function} {} vr_val (@var{val})
- Each time this function is called, it places the value of its argument
- at the end of the list of values to return from the current function.
- Once @code{vr_val} has been called, there is no way to go back to the
- beginning of the list and rewrite any of the return values. This
- function may only be called within functions that have been declared to
- return an unspecified number of output arguments (by using the special
- ellipsis notation described above).
- @end deftypefn
-
- @node Returning From a Function, Function Files, Variable-length Return Lists, Functions and Scripts
- @section Returning From a Function
-
- The body of a user-defined function can contain a @code{return} statement.
- This statement returns control to the rest of the Octave program. It
- looks like this:
-
- @example
- return
- @end example
-
- Unlike the @code{return} statement in C, Octave's @code{return}
- statement cannot be used to return a value from a function. Instead,
- you must assign values to the list of return variables that are part of
- the @code{function} statement. The @code{return} statement simply makes
- it easier to exit a function from a deeply nested loop or conditional
- statement.
-
- Here is an example of a function that checks to see if any elements of a
- vector are nonzero.
-
- @example
- @group
- function retval = any_nonzero (v)
- retval = 0;
- for i = 1:length (v)
- if (v (i) != 0)
- retval = 1;
- return;
- endif
- endfor
- printf ("no nonzero elements found\n");
- endfunction
- @end group
- @end example
-
- Note that this function could not have been written using the
- @code{break} statement to exit the loop once a nonzero value is found
- without adding extra logic to avoid printing the message if the vector
- does contain a nonzero element.
-
- @defvr {Keyword} return
- When Octave encounters the keyword @code{return} inside a function or
- script, it returns control to be caller immediately. At the top level,
- the return statement is ignored. A @code{return} statement is assumed
- at the end of every function definition.
- @end defvr
-
- @defvr {Built-in Variable} return_last_computed_value
- If the value of @code{return_last_computed_value} is true, and a
- function is defined without explicitly specifying a return value, the
- function will return the value of the last expression. Otherwise, no
- value will be returned. The default value is 0.
-
- For example, the function
-
- @example
- function f ()
- 2 + 2;
- endfunction
- @end example
-
- @noindent
- will either return nothing, if the value of
- @code{return_last_computed_value} is 0, or 4, if the value of
- @code{return_last_computed_value} is nonzero.
- @end defvr
-
- @node Function Files, Script Files, Returning From a Function, Functions and Scripts
- @section Function Files
- @cindex function file
-
- Except for simple one-shot programs, it is not practical to have to
- define all the functions you need each time you need them. Instead, you
- will normally want to save them in a file so that you can easily edit
- them, and save them for use at a later time.
-
- Octave does not require you to load function definitions from files
- before using them. You simply need to put the function definitions in a
- place where Octave can find them.
-
- When Octave encounters an identifier that is undefined, it first looks
- for variables or functions that are already compiled and currently
- listed in its symbol table. If it fails to find a definition there, it
- searches the list of directories specified by the built-in variable
- @code{LOADPATH} for files ending in @file{.m} that have the same base
- name as the undefined identifier.@footnote{The @samp{.m} suffix was
- chosen for compatibility with @sc{Matlab}.} Once Octave finds a file
- with a name that matches, the contents of the file are read. If it
- defines a @emph{single} function, it is compiled and executed.
- @xref{Script Files}, for more information about how you can define more
- than one function in a single file.
-
- When Octave defines a function from a function file, it saves the full
- name of the file it read and the time stamp on the file. After
- that, it checks the time stamp on the file every time it needs the
- function. If the time stamp indicates that the file has changed since
- the last time it was read, Octave reads it again.
-
- Checking the time stamp allows you to edit the definition of a function
- while Octave is running, and automatically use the new function
- definition without having to restart your Octave session. Checking the
- time stamp every time a function is used is rather inefficient, but it
- has to be done to ensure that the correct function definition is used.
-
- To avoid degrading performance unnecessarily by checking the time stamps
- on functions that are not likely to change, Octave assumes that function
- files in the directory tree
- @file{@var{octave-home}/share/octave/@var{version}/m}
- will not change, so it doesn't have to check their time stamps every time the
- functions defined in those files are used. This is normally a very good
- assumption and provides a significant improvement in performance for the
- function files that are distributed with Octave.
-
- If you know that your own function files will not change while you are
- running Octave, you can improve performance by setting the variable
- @code{ignore_function_time_stamp} to @code{"all"}, so that Octave will
- ignore the time stamps for all function files. Setting it to
- @code{"system"} gives the default behavior. If you set it to anything
- else, Octave will check the time stamps on all function files.
-
- @c XXX FIXME XXX -- note about time stamps on files in NFS environments?
-
- @defvr {Built-in Variable} LOADPATH
- A colon separated list of directories in which to search for function
- files. @xref{Functions and Scripts}. The value of @code{LOADPATH}
- overrides the environment variable @code{OCTAVE_PATH}. @xref{Installation}.
-
- @code{LOADPATH} is now handled in the same way as @TeX{} handles
- @code{TEXINPUTS}. If the path starts with @samp{:}, the standard path
- is prepended to the value of @code{LOADPATH}. If it ends with @samp{:}
- the standard path is appended to the value of @code{LOADPATH}.
-
- In addition, if any path element ends in @samp{//}, that directory and
- all subdirectories it contains are searched recursively for function
- files. This can result in a slight delay as Octave caches the lists of
- files found in the @code{LOADPATH} the first time Octave searches for a
- function. After that, searching is usually much faster because Octave
- normally only needs to search its internal cache for files.
-
- To improve performance of recursive directory searching, it is best for
- each directory that is to be searched recursively to contain
- @emph{either} additional subdirectories @emph{or} function files, but
- not a mixture of both.
-
- @xref{Organization of Functions} for a description of the function file
- directories that are distributed with Octave.
- @end defvr
-
- @defvr {Built-in Variable} ignore_function_time_stamp
- This variable can be used to prevent Octave from making the system call
- @code{stat} each time it looks up functions defined in function files.
- If @code{ignore_function_time_stamp} to @code{"system"}, Octave will not
- automatically recompile function files in subdirectories of
- @file{@var{octave-home}/lib/@var{version}} if they have changed since
- they were last compiled, but will recompile other function files in the
- @code{LOADPATH} if they change. If set to @code{"all"}, Octave will not
- recompile any function files unless their definitions are removed with
- @code{clear}. For any other value of @code{ignore_function_time_stamp},
- Octave will always check to see if functions defined in function files
- need to recompiled. The default value of @code{ignore_function_time_stamp} is
- @code{"system"}.
- @end defvr
-
- @defvr {Built-in Variable} warn_function_name_clash
- If the value of @code{warn_function_name_clash} is nonzero, a warning is
- issued when Octave finds that the name of a function defined in a
- function file differs from the name of the file. (If the names
- disagree, the name declared inside the file is ignored.) If the value
- is 0, the warning is omitted. The default value is 1.
- @end defvr
-
- @node Script Files, Dynamically Linked Functions, Function Files, Functions and Scripts
- @section Script Files
-
- A script file is a file containing (almost) any sequence of Octave
- commands. It is read and evaluated just as if you had typed each
- command at the Octave prompt, and provides a convenient way to perform a
- sequence of commands that do not logically belong inside a function.
-
- Unlike a function file, a script file must @emph{not} begin with the
- keyword @code{function}. If it does, Octave will assume that it is a
- function file, and that it defines a single function that should be
- evaluated as soon as it is defined.
-
- A script file also differs from a function file in that the variables
- named in a script file are not local variables, but are in the same
- scope as the other variables that are visible on the command line.
-
- Even though a script file may not begin with the @code{function}
- keyword, it is possible to define more than one function in a single
- script file and load (but not execute) all of them at once. To do
- this, the first token in the file (ignoring comments and other white
- space) must be something other than @code{function}. If you have no
- other statements to evaluate, you can use a statement that has no
- effect, like this:
-
- @example
- @group
- # Prevent Octave from thinking that this
- # is a function file:
-
- 1;
-
- # Define function one:
-
- function one ()
- ...
- @end group
- @end example
-
- To have Octave read and compile these functions into an internal form,
- you need to make sure that the file is in Octave's @code{LOADPATH}, then
- simply type the base name of the file that contains the commands.
- (Octave uses the same rules to search for script files as it does to
- search for function files.)
-
- If the first token in a file (ignoring comments) is @code{function},
- Octave will compile the function and try to execute it, printing a
- message warning about any non-whitespace characters that appear after
- the function definition.
-
- Note that Octave does not try to look up the definition of any identifier
- until it needs to evaluate it. This means that Octave will compile the
- following statements if they appear in a script file, or are typed at
- the command line,
-
- @example
- @group
- # not a function file:
- 1;
- function foo ()
- do_something ();
- endfunction
- function do_something ()
- do_something_else ();
- endfunction
- @end group
- @end example
-
- @noindent
- even though the function @code{do_something} is not defined before it is
- referenced in the function @code{foo}. This is not an error because
- Octave does not need to resolve all symbols that are referenced by a
- function until the function is actually evaluated.
-
- Since Octave doesn't look for definitions until they are needed, the
- following code will always print @samp{bar = 3} whether it is typed
- directly on the command line, read from a script file, or is part of a
- function body, even if there is a function or script file called
- @file{bar.m} in Octave's @code{LOADPATH}.
-
- @example
- @group
- eval ("bar = 3");
- bar
- @end group
- @end example
-
- Code like this appearing within a function body could fool Octave if
- definitions were resolved as the function was being compiled. It would
- be virtually impossible to make Octave clever enough to evaluate this
- code in a consistent fashion. The parser would have to be able to
- perform the call to @code{eval} at compile time, and that would be
- impossible unless all the references in the string to be evaluated could
- also be resolved, and requiring that would be too restrictive (the
- string might come from user input, or depend on things that are not
- known until the function is evaluated).
-
- Although Octave normally executes commands from script files that have
- the name @file{@var{file}.m}, you can use the function @code{source} to
- execute commands from any file.
-
- @deftypefn {Built-in Function} {} source (@var{file})
- Parse and execute the contents of @var{file}. This is equivalent to
- executing commands from a script file, but without requiring the file to
- be named @file{@var{file}.m}.
- @end deftypefn
-
- @node Dynamically Linked Functions, Organization of Functions, Script Files, Functions and Scripts
- @section Dynamically Linked Functions
- @cindex dynamic linking
-
- On some systems, Octave can dynamically load and execute functions
- written in C++. Octave can only directly call functions written in C++,
- but you can also load functions written in other languages
- by calling them from a simple wrapper function written in C++.
-
- Here is an example of how to write a C++ function that Octave can load,
- with commentary. The source for this function is included in the source
- distributions of Octave, in the file @file{examples/oregonator.cc}. It
- defines the same set of differential equations that are used in the
- example problem of @ref{Ordinary Differential Equations}. By running
- that example and this one, we can compare the execution times to see
- what sort of increase in speed you can expect by using dynamically
- linked functions.
-
- The function defined in @file{oregonator.cc} contains just 8 statements,
- and is not much different than the code defined in the corresponding
- M-file (also distributed with Octave in the file
- @file{examples/oregonator.m}).
-
- Here is the complete text of @file{oregonator.cc}:
-
- just
-
- @example
- @group
- #include <octave/oct.h>
-
- DEFUN_DLD (oregonator, args, ,
- "The `oregonator'.")
- @{
- ColumnVector dx (3);
-
- ColumnVector x = args(0).vector_value ();
-
- dx(0) = 77.27 * (x(1) - x(0)*x(1) + x(0)
- - 8.375e-06*pow (x(0), 2));
-
- dx(1) = (x(2) - x(0)*x(1) - x(1)) / 77.27;
-
- dx(2) = 0.161*(x(0) - x(2));
-
- return octave_value (dx);
- @}
- @end group
- @end example
-
- The first line of the file,
-
- @example
- #include <octave/oct.h>
- @end example
-
- @noindent
- includes declarations for all of Octave's internal functions that you
- will need. If you need other functions from the standard C++ or C
- libraries, you can include the necessary headers here.
-
- The next two lines
- @example
- @group
- DEFUN_DLD (oregonator, args, ,
- "The `oregonator'.")
- @end group
- @end example
-
- @noindent
- declares the function. The macro @code{DEFUN_DLD} and the macros that
- it depends on are defined in the files @file{defun-dld.h},
- @file{defun.h}, and @file{defun-int.h} (these files are included in the
- header file @file{octave/oct.h}).
-
- Note that the third parameter to @code{DEFUN_DLD} (@code{nargout}) is
- not used, so it is omitted from the list of arguments to in order to
- avoid the warning from gcc about an unused function parameter.
-
- @noindent
- simply declares an object to store the right hand sides of the
- differential equation, and
-
- The statement
-
- @example
- ColumnVector x = args(0).vector_value ();
- @end example
-
- @noindent
- extracts a column vector from the input arguments. The variable
- @code{args} is passed to functions defined with @code{DEFUN_DLD} as an
- @code{octave_value_list} object, which includes methods for getting the
- length of the list and extracting individual elements.
-
- In this example, we don't check for errors, but that is not difficult.
- All of the Octave's built-in functions do some form of checking on their
- arguments, so you can check the source code for those functions for
- examples of various strategies for verifying that the correct number and
- types of arguments have been supplied.
-
- The next statements
-
- @example
- @group
- ColumnVector dx (3);
-
- dx(0) = 77.27 * (x(1) - x(0)*x(1) + x(0)
- - 8.375e-06*pow (x(0), 2));
-
- dx(1) = (x(2) - x(0)*x(1) - x(1)) / 77.27;
-
- dx(2) = 0.161*(x(0) - x(2));
- @end group
- @end example
-
- @noindent
- define the right hand side of the differential equation. Finally, we
- can return @code{dx}:
-
- @example
- return octave_value (dx);
- @end example
-
- @noindent
- The actual return type is @code{octave_value_list}, but it is only
- necessary to convert the return type to an @code{octave_value} because
- there is a default constructor that can automatically create an object
- of that type from an @code{octave_value} object, so we can just use that
- instead.
-
- To use this file, your version of Octave must support dynamic linking.
- To find out if it does, type the command
- @kbd{octave_config_info ("dld")} at the Octave prompt. Support for
- dynamic linking is included if this command returns 1.
-
- To compile the example file, type the command @samp{mkoctfile
- oregonator.cc} at the shell prompt. The script @code{mkoctfile} should
- have been installed along with Octave. Running it will create a file
- called @file{oregonator.oct} that can be loaded by Octave. To test the
- @file{oregonator.oct} file, start Octave and type the command
-
- @example
- oregonator ([1, 2, 3], 0)
- @end example
-
- @noindent
- at the Octave prompt. Octave should respond by printing
-
- @example
- @group
- ans =
-
- 77.269353
- -0.012942
- -0.322000
- @end group
- @end example
-
- You can now use the @file{oregonator.oct} file just as you would the
- @code{oregonator.m} file to solve the set of differential equations.
-
- On a 133 MHz Pentium running Linux, Octave can solve the problem shown
- in @ref{Ordinary Differential Equations} in about 1.4 second using the
- dynamically linked function, compared to about 19 seconds using the
- M-file. Similar decreases in execution time can be expected for other
- functions, particularly those that rely on functions like @code{lsode}
- that require user-supplied functions.
-
- Additional examples are available in the files in the @file{src}
- directory of the Octave distribution. Currently, this includes the
- files
-
- @example
- @group
- balance.cc fft2.cc inv.cc qzval.cc
- chol.cc filter.cc log.cc schur.cc
- colloc.cc find.cc lsode.cc sort.cc
- dassl.cc fsolve.cc lu.cc svd.cc
- det.cc givens.cc minmax.cc syl.cc
- eig.cc hess.cc pinv.cc
- expm.cc ifft.cc qr.cc
- fft.cc ifft2.cc quad.cc
- @end group
- @end example
-
- @noindent
- These files use the macro @code{DEFUN_DLD_BUILTIN} instead of
- @code{DEFUN_DLD}. The difference between these two macros is just that
- @code{DEFUN_DLD_BUILTIN} can define a built-in function that is not
- dynamically loaded if the operating system does not support dynamic
- linking. To define your own dynamically linked functions you should use
- @code{DEFUN_DLD}.
-
- There is currently no detailed description of all the functions that you
- can call in a built-in function. For the time being, you will have to
- read the source code for Octave.
-
- @node Organization of Functions, , Dynamically Linked Functions, Functions and Scripts
- @section Organization of Functions Distributed with Octave
-
- Many of Octave's standard functions are distributed as function files.
- They are loosely organized by topic, in subdirectories of
- @file{@var{octave-home}/lib/octave/@var{version}/m}, to make it easier
- to find them.
-
- The following is a list of all the function file subdirectories, and the
- types of functions you will find there.
-
- @table @file
- @item audio
- Functions for playing and recording sounds.
-
- @item control
- Functions for design and simulation of automatic control systems.
-
- @item elfun
- Elementary functions.
-
- @item general
- Miscellaneous matrix manipulations, like @code{flipud}, @code{rot90},
- and @code{triu}, as well as other basic functions, like
- @code{is_matrix}, @code{nargchk}, etc.
-
- @item image
- Image processing tools. These functions require the X Window System.
-
- @item io
- Input-ouput functions.
-
- @item linear-algebra
- Functions for linear algebra.
-
- @item miscellaneous
- Functions that don't really belong anywhere else.
-
- @item plot
- A set of functions that implement the @sc{Matlab}-like plotting functions.
-
- @item polynomial
- Functions for manipulating polynomials.
-
- @item set
- Functions for creating and manipulating sets of unique values.
-
- @item signal
- Functions for signal processing applications.
-
- @item specfun
- Special functions.
-
- @item special-matrix
- Functions that create special matrix forms.
-
- @item startup
- Octave's system-wide startup file.
-
- @item statistics
- Statistical functions.
-
- @item strings
- Miscellaneous string-handling functions.
-
- @item time
- Functions related to time keeping.
- @end table
-